from fastapi import FastAPI
import uvicorn
from typing import Optional
from pydantic import BaseModel
from fastapi import Query, Body, status
from pydantic import validator, Field
from fastapi.responses import JSONResponse
from fastapi.exceptions import RequestValidationError
import pydantic
from fastapi import Depends

app = FastAPI()


class PageLimitParamModel(BaseModel):
    page: Optional[int]
    size: int = Query(..., embed=True)
    name: str = Query('Tom')


class PageLimitParamModel2(object):
    def __init__(self, page: Optional[int] = 1, size1: str = Body('ss'), size2: str = Body('ss'), name: str = Query('Tom')):
        self.page = page
        self.size1 = size1
        self.size2 = size2
        self.name = name


class PageLimitParamModel3(object):
    def __init__(self, page: Optional[int] = 1, size1: str = Body('ss'), name: str = Query('Tom')):
        self.page = page
        self.size1 = size1
        self.name = name


"""
common: Model这种模式的都是从json body里获取
如果json要求传递的参数只有一个，那么一般要加上 embed=True，因为如果body json参数只有一个，会认为整个body就是value
如果要把请求参数封装在Depends，那么只能使用普通类__init__(Body(), Query())的模式

def hello(common: pydantic.BaseModel = Depends()) 这种语法没有错误，但是逻辑错误，因为Depends读取的是class的__init__的参数
这样书写会导致失效
"""

# http get ':9999/test1'
# http get ':9999/test1?age1=1' age2=2
# http get ':9999/test1?age1=1' age1=99 age2=4 common:='{"size": 10}'
@app.get('/test1')
async def test1(common: PageLimitParamModel, age1: int = Query(...), age2: int = Body(...)):
    return {'page': common.page, 'size': common.size, 'name': common.name, 'age1': age1, 'age2': age2}


# http get ':9999/test11?age1=1' age1=99 common:='{"size": 10}' # error
# http get ':9999/test11?age1=1' size=111
@app.get('/test11')
async def test11(common: PageLimitParamModel, age1: int = Query(...)):
    return {'page': common.page, 'size': common.size, 'name': common.name, 'age1': age1}


# http get ':9999/test2'
@app.get('/test2')
async def test2(common: PageLimitParamModel = Depends()):
    return {'page': common.page, 'size': common.size, 'name': common.name}


# http post ':9999/test3'
@app.post('/test3')
async def test3(common: PageLimitParamModel3 = Depends()):
    return {'page': common.page, 'size': [common.size1, common.size1], 'name': common.name}


if __name__ == '__main__':
    uvicorn.run('__main__:app', port=9999, reload=True)

